﻿#region Includes

using System;
using System.Collections.Generic;
using System.Reflection;
using ArtheaEngine;
using ArtheaEngine.Model;

#endregion

namespace ArtheaServer.Commands
{
    public abstract class Command : IComparable<Command>, IEqualityComparer<ICommand>
    {
        protected static readonly ISet<Command> Commands = new HashSet<Command>();

        static Command()
        {
            foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
            {
                if (!type.IsSubclassOf(typeof (Command)) || type.IsAbstract)
                    continue;

                Commands.Add((Command) Activator.CreateInstance(type));
            }
        }

        protected Command(string name)
        {
            Name = name;
            Level = 0;
            Aliases = new HashSet<string>();
        }

        protected Command(string name, string descr)
            : this(name)
        {
            Description = descr;
        }

        protected Command(string name, string descr, short level)
        {
            Name = name;
            Description = descr;
            Level = level;
            Aliases = new HashSet<string>();
        }

        public static void Interpret(Character ch, Argument argument)
        {
            if (argument.IsEmpty())
            {
                return;
            }


            if (Social.Interpret(ch, argument))
            {
                return;
            }

            var arg = argument.Next();
            foreach (var cmd in Commands)
            {
                if (!cmd.CanUse(ch))
                    continue;

                if (cmd.Name.StartsWith(arg, StringComparison.CurrentCultureIgnoreCase))
                {
                    cmd.Execute(ch, argument);
                    return;
                }

                foreach (var alias in cmd.Aliases)
                {
                    if (alias.StartsWith(arg, StringComparison.CurrentCultureIgnoreCase))
                    {
                        cmd.Execute(ch, argument);
                        return;
                    }
                }
            }

            ch.WriteLine("Huh?");
        }

        public virtual bool CanUse(Character ch)
        {
            return Level <= ch.Level;
        }

        public abstract void Execute(Character ch, Argument argument);

        public HashSet<string> Aliases { get; protected set; }
        public string Description { get; protected set; }
        public short Level { get; protected set; }
        protected byte ListPriority { get; set; }

        public string Name { get; protected set; }

        #region IComparable<Command> Members

        public int CompareTo(Command other)
        {
            return Name.CompareTo(other.Name) & ListPriority.CompareTo(other.ListPriority);
        }

        #endregion

        #region IEqualityComparer<ICommand> Members

        public bool Equals(ICommand x, ICommand y)
        {
            return x.Name.Equals(y.Name);
        }

        public int GetHashCode(ICommand obj)
        {
            return obj.Name.GetHashCode();
        }

        #endregion
    }
}